package org.xbdframework.sample.sso.authserver.filter.customLogin;

import org.springframework.security.config.annotation.web.HttpSecurityBuilder;
import org.springframework.security.config.annotation.web.configurers.AbstractHttpConfigurer;
import org.springframework.security.config.annotation.web.configurers.DefaultLoginPageConfigurer;
import org.springframework.security.web.authentication.UsernamePasswordAuthenticationFilter;
import org.springframework.security.web.authentication.ui.DefaultLogoutPageGeneratingFilter;
import org.springframework.security.web.csrf.CsrfToken;

import javax.servlet.http.HttpServletRequest;
import java.util.Collections;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;

/**
 * @Author: Mr.Liu
 * @description: 自定义默认登陆页面的配置
 * @date: 2023/8/8 9:37
 * @version: 1.0.0
 * @copyright: 中道新职坊
 */


public class CustomDefaultLoginPageConfigurer<H extends HttpSecurityBuilder<H>> extends
        AbstractHttpConfigurer<DefaultLoginPageConfigurer<H>, H> {

    private CustomDefaultLoginPageGeneratingFilter loginPageGeneratingFilterFilter = new CustomDefaultLoginPageGeneratingFilter();
    private DefaultLogoutPageGeneratingFilter logoutPageGeneratingFilter = new DefaultLogoutPageGeneratingFilter();

    @Override
    public void init(H http) {
        initDefaultLoginFilter(http);
        initDefaultLogoutFilter(http);
    }

    @Override
    public void configure(H http) {
        if (loginPageGeneratingFilterFilter.isEnabled()) {
            loginPageGeneratingFilterFilter = postProcess(loginPageGeneratingFilterFilter);
            http.addFilterAfter(loginPageGeneratingFilterFilter, UsernamePasswordAuthenticationFilter.class);
            http.addFilter(this.logoutPageGeneratingFilter);
        }
    }

    private void initDefaultLoginFilter(H http) {
        Function<HttpServletRequest, Map<String, String>> resolveHiddenInputs = request -> {
            Map<String, String> map = new HashMap<>();
            CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
            if (token != null) {
                map.put(token.getParameterName(), token.getToken());
            }
            Enumeration<String> parameterNames = request.getParameterNames();
            while (parameterNames.hasMoreElements()) {
                String paramName = parameterNames.nextElement();
                String paramValue = request.getParameter(paramName);
                map.put(paramName, paramValue);
            }
            return map;
        };
        loginPageGeneratingFilterFilter.setFormLoginEnabled(true);
        loginPageGeneratingFilterFilter.setUsernameParameter("username");
        loginPageGeneratingFilterFilter.setPasswordParameter("password");
        loginPageGeneratingFilterFilter.setLoginPageUrl("/login");
        loginPageGeneratingFilterFilter.setFailureUrl("/login?error");
        loginPageGeneratingFilterFilter.setAuthenticationUrl("/login");
        loginPageGeneratingFilterFilter.setResolveHiddenInputs(resolveHiddenInputs);
        http.setSharedObject(CustomDefaultLoginPageGeneratingFilter.class, loginPageGeneratingFilterFilter);
    }

    private void initDefaultLogoutFilter(H http) {
        Function<HttpServletRequest, Map<String, String>> hiddenInputs = request -> {
            CsrfToken token = (CsrfToken) request.getAttribute(CsrfToken.class.getName());
            if (token == null) {
                return Collections.emptyMap();
            }
            return Collections.singletonMap(token.getParameterName(), token.getToken());
        };
        this.logoutPageGeneratingFilter.setResolveHiddenInputs(hiddenInputs);
        http.setSharedObject(DefaultLogoutPageGeneratingFilter.class,
                logoutPageGeneratingFilter);
    }

}
